package com.g8.pethospitallearnbackend.service.impls;

import com.g8.pethospitallearnbackend.entity.Flow;
import com.g8.pethospitallearnbackend.entity.FlowExample;
import com.g8.pethospitallearnbackend.entity.FlowOrderChangeInBulk;
import com.g8.pethospitallearnbackend.exception.CustomException;
import com.g8.pethospitallearnbackend.mapper.FlowMapper;
import com.g8.pethospitallearnbackend.mapper.RoleMapper;
import com.g8.pethospitallearnbackend.service.FlowService;
import com.g8.pethospitallearnbackend.service.OperationService;
import com.g8.pethospitallearnbackend.utils.NewIdGenerateUtil;
import com.g8.pethospitallearnbackend.utils.responseUtil.ResponseStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class FlowServiceImpl implements FlowService {
    @Autowired
    private FlowMapper flowMapper;
    @Autowired
    private OperationService operationService;

    /**
     * 获取一个角色的所有流程，要按照流程的顺序排序
     * @param roleId
     * @return
     */
    @Override
    public List<Flow> getFlowsOfARole(String roleId) {
        FlowExample flowExample = new FlowExample();
        flowExample.setOrderByClause("flow_order");
        flowExample.createCriteria().andRoleIdEqualTo(roleId);
        List<Flow> flows =  flowMapper.selectByExample(flowExample);
        for(Flow f : flows) {
            f.setFlowOperations(operationService.getOpsOfAFlow(f.getFlowId()));
        }
        return flows;
    }

    @Override
    public Flow getAFlowById(String flowId) {
        Flow flow = flowMapper.selectByPrimaryKey(flowId);
        if (flow == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到该流程！");
        else flow.setFlowOperations(operationService.getOpsOfAFlow(flowId));
        return flow;
    }

    @Override
    public List<Flow> getFlowsByName(String flowName) {
        FlowExample flowExample = new FlowExample();
        flowExample.createCriteria().andFlowNameLike("%" + flowName + "%");
        List<Flow> flows = flowMapper.selectByExample(flowExample);
        for(Flow f : flows) {
            f.setFlowOperations(operationService.getOpsOfAFlow(f.getFlowId()));
        }
        if(flows.isEmpty()){
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到该流程！");
        }
        return flows;
    }

    @Override
    public Flow addAFlow(Flow flow) {
        if(!isValidRoleId(flow.getRoleId()))
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "该roleId不存在");
        if (flow.getFlowName().isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "流程的名称不能为空！");
        // 生成一个id
        String id = NewIdGenerateUtil.getNumber(4);
        Flow repeat = flowMapper.selectByPrimaryKey(id);
        while(repeat != null) {
            id = NewIdGenerateUtil.getNumber(4);
            repeat = flowMapper.selectByPrimaryKey(id);
        }
        flow.setFlowId(id);
        // 排序
        List<Flow> flowsOfARole = getFlowsOfARole(flow.getRoleId());
        if(!flowsOfARole.isEmpty()) {
            // 如果这个流程是插进去的，不是直接放到最后
            if(flow.getFlowOrder() <= flowsOfARole.size()) {
                // 把后面的流程都往后挪一位
                for(int i = flow.getFlowOrder()-1; i < flowsOfARole.size(); i++){
                    Flow f = flowsOfARole.get(i);
                    if (f.getFlowOrder() < flow.getFlowOrder()) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "flow排序标的序号有问题");
                    f.setFlowOrder(f.getFlowOrder()+1);
                    flowMapper.updateByPrimaryKey(f);
                }
            } // 如果放最后，直接设置一下序号，免得有跳着标序号的问题
            else flow.setFlowOrder(flowsOfARole.size() + 1);
        } else flow.setFlowOrder(1); // 如果该角色中没有流程
        flowMapper.insert(flow);
        return flowMapper.selectByPrimaryKey(id);
    }

    @Override
    public Flow modifyAFlow(Flow flow) {
        Flow flowDB = flowMapper.selectByPrimaryKey(flow.getFlowId());
        if (flowDB == null)
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到相关流程");
        // 校验一下角色id
        if (!isValidRoleId(flow.getRoleId()))
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "该角色id不存在！");
        if (flow.getFlowName().isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "流程的名称不能为空！");
        // 如果还在原来的角色
        if (flow.getRoleId().equals(flowDB.getRoleId())) {
            // 排个序
            List<Flow> flowsOfRole = this.getFlowsOfARole(flow.getRoleId());
            // 如果这个流程的顺序变了，重新排序
            // 如果这个流程跳到前面去了，把两序号（包括前一个序号）之间的都+1
            if (flow.getFlowOrder() < flowDB.getFlowOrder()) {
                for (int i = flow.getFlowOrder()-1; i < flowDB.getFlowOrder()-1; i++) {
                    Flow f = flowsOfRole.get(i);
                    f.setFlowOrder(f.getFlowOrder()+1);
                    flowMapper.updateByPrimaryKey(f);
                }
            } // 如果这个流程跳到后面去了，两序号（包括后一个序号）之间的都-1
            else if (flow.getFlowOrder() > flowDB.getFlowOrder()) {
                // 如果直接跳到最后的后面去了，那么设为最后一个
                if (flow.getFlowOrder() > flowsOfRole.size()) flow.setFlowOrder(flowsOfRole.size());
                for (int i = flowDB.getFlowOrder(); i < flow.getFlowOrder(); i++) {
                    Flow f = flowsOfRole.get(i);
                    f.setFlowOrder(f.getFlowOrder()-1);
                    flowMapper.updateByPrimaryKey(f);
                }
            }
            // 然后更新本flow
            flowMapper.updateByPrimaryKey(flow);
        } // 如果换了个角色
        else {
            // 原来流程里后面的都往前走一下
            List<Flow> flowsOfOriginalRole = this.getFlowsOfARole(flowDB.getRoleId());
            for(int i = flowDB.getFlowOrder(); i < flowsOfOriginalRole.size(); i++) {
                Flow f = flowsOfOriginalRole.get(i);
                f.setFlowOrder(f.getFlowOrder()-1);
                flowMapper.updateByPrimaryKey(f);
            }
            // 删除原来的
            flowMapper.deleteByPrimaryKey(flowDB.getFlowId());
            // 该流程插入到新的角色中去
            List<Flow> flowsOfNowRole = getFlowsOfARole(flow.getRoleId());
            // 排序
            if(!flowsOfNowRole.isEmpty()) {
                // 如果这个流程是插进去的，不是直接放到最后
                if(flow.getFlowOrder() <= flowsOfNowRole.size()) {
                    // 把后面的流程都往后挪一位
                    for(int i = flow.getFlowOrder()-1; i < flowsOfNowRole.size(); i++){
                        Flow f = flowsOfNowRole.get(i);
                        if (f.getFlowOrder() < flow.getFlowOrder()) throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "flow排序标的序号有问题");
                        f.setFlowOrder(f.getFlowOrder()+1);
                        flowMapper.updateByPrimaryKey(f);
                    }
                } // 如果放最后，直接设置一下序号，免得有跳着标序号的问题
                else flow.setFlowOrder(flowsOfNowRole.size() + 1);
            } else flow.setFlowOrder(1); // 如果该角色中没有流程
            flowMapper.insert(flow);
        }
        return this.getAFlowById(flow.getFlowId());
    }

    @Override
    public String deleteAFlow(String flowId) {
        Flow flow = flowMapper.selectByPrimaryKey(flowId);
        if (flow == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到要删除的流程");
        // 原来流程里后面的都往前走一下
        List<Flow> flowsOfOriginalRole = this.getFlowsOfARole(flow.getRoleId());
        for(int i = flow.getFlowOrder(); i < flowsOfOriginalRole.size(); i++) {
            Flow f = flowsOfOriginalRole.get(i);
            f.setFlowOrder(f.getFlowOrder()-1);
            flowMapper.updateByPrimaryKey(f);
        }
        // 删除原来的
        if(flowMapper.deleteByPrimaryKey(flow.getFlowId()) == 1) return "删除成功";
        throw new CustomException(ResponseStatusEnum.SYSTEM_ERROR, "删除不成功");
    }


    @Autowired
    private RoleMapper roleMapper;

    public boolean isValidRoleId(String roleId) {
        if (roleId.isBlank()) throw new CustomException(ResponseStatusEnum.MISS_PARAM, "该操作属于的角色roleId缺失！");
        if (roleMapper.selectByPrimaryKey(roleId) != null) return true;
        return false;
    }

    @Override
    public String modifyFLowOrderInBulk(FlowOrderChangeInBulk bulk) {
        if (bulk == null) throw new CustomException(ResponseStatusEnum.MISS_PARAM);
        String roleId = bulk.getRoleId();
        int count = 0;
        if (roleMapper.selectByPrimaryKey(roleId) == null)
            throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到该角色");
        List<String> orderedIds = bulk.getAllFlowIds();
        if (this.getFlowsOfARole(roleId).size() != orderedIds.size())
            throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "提供的该角色流程不全！");
        StringBuffer msg = new StringBuffer();
        for (int i = 0; i < orderedIds.size(); i++) {
            String flowId = orderedIds.get(i);
            Flow flow = this.getAFlowById(flowId);
            if (flow == null) throw new CustomException(ResponseStatusEnum.DATA_NOT_EXIST, "未查询到流程"+flowId);
            if (!flow.getRoleId().equals(roleId))
                throw new CustomException(ResponseStatusEnum.BAD_REQUEST, "流程"+flowId+"不是角色"+roleId+"的流程！");
            flow.setFlowOrder(i+1);
            if (flowMapper.updateByPrimaryKey(flow) < 1)
                msg.append("流程").append(flowId).append("更新失败\n");
            else count++;
        }
        if (count == orderedIds.size()) msg.append("流程顺序修改成功");
        return msg.toString();
    }
}
